package com.example.fileprovider;

import android.util.Xml;
import com.example.office.CryptUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

public class Docx2Html implements Htmlable {
    private OfficePicMgr picMgr;

    private static final String head = "<!DOCTYPE><html><meta charset=\"utf-8\"><body>";// 定义头文件,我在这里加了utf-8,不然会出现乱码
    private static final String end = "</body></html>";
    private static final String tagBegin = "<p>";// 段落开始,标记开始?
    private static final String tagEnd = "</p>";// 段落结束
    private static final String tableBegin = "<table style=\"border-collapse:collapse\" border=1 bordercolor=\"black\">";
    private static final String tableEnd = "</table>";
    private static final String rowBegin = "<tr>";
    private static final String rowEnd = "</tr>";
    private static final String colBegin = "<td>";
    private static final String colEnd = "</td>";


    private String filePath;//文件路径
    private ByteArrayOutputStream output = new ByteArrayOutputStream();//写入html的全局文件输出流


    private boolean isPenddingTagPic = false; // 是否有tag = pic 标签未处理
    private HashMap<String, String> picResMap;

    // TODO:初始化 映射表 word/_rels/document.xml.rels
    private void initXmlRels() {
        try {
            picResMap = new HashMap<String, String>();
            ZipFile zipFile = new ZipFile(new File(this.filePath));
            ZipEntry sharedStringXML = zipFile.getEntry("word/_rels/document.xml.rels");
            InputStream inputStream = zipFile.getInputStream(sharedStringXML);
            XmlPullParser xmlParser = Xml.newPullParser();
            xmlParser.setInput(inputStream, "utf-8");
            //
            int evtType = xmlParser.getEventType();
            while(evtType != XmlPullParser.END_DOCUMENT) {
                switch(evtType) {
                    case XmlPullParser.START_TAG:
                        String tag = xmlParser.getName();
                        if("Relationship".equals(tag)) {
                            String attrId = xmlParser.getAttributeValue(0); // Target Id
                            String target = xmlParser.getAttributeValue(2);
                            picResMap.put(attrId, target);
                            LogMgr.d(attrId + " = " + target);
                        }
                        //
                        LogMgr.d(tag);
                        break;
                    default:
                        break;
                }
                evtType = xmlParser.next();
            }
        } catch(ZipException e) {
            e.printStackTrace();
        } catch(XmlPullParserException e) {
            e.printStackTrace();
        } catch(IOException e) {
            e.printStackTrace();
        } catch(Exception e) {
            e.printStackTrace();
        }

        // for test
        Iterator iter = picResMap.entrySet().iterator();
        while(iter.hasNext()) {
            HashMap.Entry entry = (HashMap.Entry) iter.next();
            Object key = entry.getKey();
            Object val = entry.getValue();
            LogMgr.d(key + "=" + val);
        }
    }

    @Override
    public InputStream getHtmlInputStream() {
        if(output == null) {
            LogMgr.d("解析出错");
            return null;
        }

        byte[] bytes = output.toByteArray();
        try {
            output.write(bytes);
        } catch(IOException e) {
            e.printStackTrace();
        }

        return new ByteArrayInputStream(bytes);
    }


    public Docx2Html(String filePath) {
        this.filePath = filePath;
        int index1 = filePath.lastIndexOf("/");
        String picturePath = filePath.substring(0, index1);
        String prefix = filePath.substring(index1 + 1, filePath.lastIndexOf("."));//文件名，不包含路径以及后缀名
        picMgr = new OfficePicMgr(picturePath, prefix);
    }

    /**
     * 读取07及以上版本的word文档
     * 2013-5-15 下午2:38:33 chenhao添加此方法
     */
    @Override
    public boolean convertToHtml() {
        String river = "";
        try {
            this.output.write(head.getBytes());// 写如头部

            ZipFile zipFile = new ZipFile(new File(this.filePath));
            ZipEntry sharedStringXML = zipFile.getEntry("word/document.xml");
            InputStream inputStream = zipFile.getInputStream(sharedStringXML);
            XmlPullParser xmlParser = Xml.newPullParser();
            xmlParser.setInput(inputStream, "utf-8");
            int evtType = xmlParser.getEventType();
            boolean isTable = false; // 是表格 用来统计 列 行 数
            boolean isSize = false; // 大小状态
            boolean isColor = false; // 颜色状态
            boolean isCenter = false; // 居中状态
            boolean isRight = false; // 居右状态
            boolean isItalic = false; // 是斜体
            boolean isUnderline = false; // 是下划线
            boolean isBold = false; // 加粗
            boolean isR = false; // 在那个r中

            int pictureIndex = 1; // docx 压缩包中的图片名 iamge1 开始 所以索引从1开始
            while(evtType != XmlPullParser.END_DOCUMENT) {
                switch(evtType) {
                    // 开始标签
                    case XmlPullParser.START_TAG:
                        String tag = xmlParser.getName();
                        // LogMgr.v(tag);

                        if(tag.equals("blip")) {
                            // TODO:
                            if(isPenddingTagPic) {
                                if(picResMap == null) {
                                    initXmlRels();
                                }
                                String attrId = xmlParser.getAttributeValue(0);
                                String name = picResMap.get(attrId);
                                if(name != null) {
                                    handlePic(zipFile, name);
                                }
                                isPenddingTagPic = false;
                                break;
                            }
                        }
                        if(tag.equalsIgnoreCase("r")) {
                            isR = true;
                        }
                        if(tag.equalsIgnoreCase("u")) { // 判断下划线
                            isUnderline = true;
                        }
                        if(tag.equalsIgnoreCase("jc")) { // 判断对齐方式
                            String align = xmlParser.getAttributeValue(0);
                            if(align.equals("center")) {
                                this.output.write("<center>".getBytes());
                                isCenter = true;
                            }
                            if(align.equals("right")) {
                                this.output.write("<div align=\"right\">".getBytes());
                                isRight = true;
                            }
                        }
                        if(tag.equalsIgnoreCase("color")) { // 判断颜色
                            String color = xmlParser.getAttributeValue(0);
                            this.output.write(("<font color=" + color + ">").getBytes());
                            isColor = true;
                        }
                        if(tag.equalsIgnoreCase("sz")) { // 判断大小
                            if(isR) {
                                int size = decideSize(Integer.valueOf(xmlParser.getAttributeValue(0)));
                                this.output.write(("<font size=" + size + ">").getBytes());
                                isSize = true;
                            }
                        }

                        // 下面是表格处理
                        if(tag.equalsIgnoreCase("tbl")) { // 检测到tbl 表格开始
                            this.output.write(tableBegin.getBytes());
                            isTable = true;
                        }
                        if(tag.equalsIgnoreCase("tr")) { // 行
                            this.output.write(rowBegin.getBytes());
                        }
                        if(tag.equalsIgnoreCase("tc")) { // 列
                            this.output.write(colBegin.getBytes());
                        }

                        if(tag.equalsIgnoreCase("pic")) {
                            isPenddingTagPic = true;
                        }

                        if(tag.equalsIgnoreCase("b")) { // 检测到加粗标签
                            isBold = true;
                        }
                        if(tag.equalsIgnoreCase("p")) {// 检测到 p 标签
                            if(!isTable) { // 如果在表格中 就无视
                                this.output.write(tagBegin.getBytes());
                            }
                        }
                        if(tag.equalsIgnoreCase("i")) { // 斜体
                            isItalic = true;
                        }
                        // 检测到值 标签
                        if(tag.equalsIgnoreCase("t")) {
                            if(isBold) { // 加粗
                                this.output.write("<b>".getBytes());
                            }
                            if(isUnderline) { // 检测到下划线标签,输入<u>
                                this.output.write("<u>".getBytes());
                            }
                            if(isItalic) { // 检测到斜体标签,输入<i>
                                output.write("<i>".getBytes());
                            }
                            river = xmlParser.nextText();
                            this.output.write(river.getBytes()); // 写入数值
                            if(isItalic) { // 检测到斜体标签,在输入值之后,输入</i>,并且斜体状态=false
                                this.output.write("</i>".getBytes());
                                isItalic = false;
                            }
                            if(isUnderline) {// 检测到下划线标签,在输入值之后,输入</u>,并且下划线状态=false
                                this.output.write("</u>".getBytes());
                                isUnderline = false;
                            }
                            if(isBold) { // 加粗
                                this.output.write("</b>".getBytes());
                                isBold = false;
                            }
                            if(isSize) { // 检测到大小设置,输入结束标签
                                this.output.write("</font>".getBytes());
                                isSize = false;
                            }
                            if(isColor) { // 检测到颜色设置存在,输入结束标签
                                this.output.write("</font>".getBytes());
                                isColor = false;
                            }
                            if(isCenter) { // 检测到居中,输入结束标签
                                this.output.write("</center>".getBytes());
                                isCenter = false;
                            }
                            if(isRight) { // 居右不能使用<right></right>,使用div可能会有状况,先用着
                                this.output.write("</div>".getBytes());
                                isRight = false;
                            }
                        }
                        break;
                    // 结束标签
                    case XmlPullParser.END_TAG:
                        String tag2 = xmlParser.getName();
                        if(tag2.equalsIgnoreCase("tbl")) { // 检测到表格结束,更改表格状态
                            this.output.write(tableEnd.getBytes());
                            isTable = false;
                        }
                        if(tag2.equalsIgnoreCase("tr")) { // 行结束
                            this.output.write(rowEnd.getBytes());
                        }
                        if(tag2.equalsIgnoreCase("tc")) { // 列结束
                            this.output.write(colEnd.getBytes());
                        }
                        if(tag2.equalsIgnoreCase("p")) { // p结束,如果在表格中就无视
                            if(!isTable) {
                                this.output.write(tagEnd.getBytes());
                            }
                        }
                        if(tag2.equalsIgnoreCase("r")) {
                            isR = false;
                        }
                        break;
                    default:
                        break;
                }
                evtType = xmlParser.next();
            }
            this.output.write(end.getBytes());
        } catch(ZipException e) {
            e.printStackTrace();
        } catch(IOException e) {
            e.printStackTrace();
        } catch(XmlPullParserException e) {
            e.printStackTrace();
        } catch(Exception e) {
            e.printStackTrace();
        }

        if(river == null) {
            river = "解析文件出现问题";
            return false;
        }
        LogMgr.d("convert succ");
        return true;
    }
    private void handlePic(final ZipFile zipFile, String name) {// 检测到标签 pic 图片
        // TODO bug丢失重复图片:如果使用相同的图片，则有问题
        // 查找<a:blip r:embed="rId6"/> 的结构 与 blip标签协同工作
        String entryName = "word/" + name;
        String saveName = name.replace("/","_");

        ZipEntry sharePicture = null;
        InputStream pictIS = null;

        sharePicture = zipFile.getEntry(entryName);
        try {
            if(sharePicture != null) {
                pictIS = zipFile.getInputStream(sharePicture);
                if(pictIS != null && picMgr != null) {
                    byte[] content = CryptUtils.stream2Bytes(pictIS);
                    String picName = picMgr.savePicture(content, null, saveName, 0, 0);
                    writePicToHtml(picName);
                    pictIS.close();
                    //
                }
            }
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    private int decideSize(int size) {
        if(size >= 1 && size <= 8) {
            return 1;
        }
        if(size >= 9 && size <= 11) {
            return 2;
        }
        if(size >= 12 && size <= 14) {
            return 3;
        }
        if(size >= 15 && size <= 19) {
            return 4;
        }
        if(size >= 20 && size <= 29) {
            return 5;
        }
        if(size >= 30 && size <= 39) {
            return 6;
        }
        if(size >= 40) {
            return 7;
        }
        return 3;
    }

    private static final String imgStr = "<img src=\"%s\" />";
    private void writePicToHtml(String name) {
        String imageString = String.format(imgStr, name);
        try {
            this.output.write(imageString.getBytes());
        } catch(Exception e) {
            e.printStackTrace();
            LogMgr.e("output Exception");
        }
    }

}
